/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiEngineDLL.h
	Macros and systems to make it easier to link to the Maxsi Engine.

******************************************************************************/

#ifndef MaxsiEngineDLL_H
#define MaxsiEngineDLL_H

BeginMaxsiNamespace

//=============================================================================
//	Detect whether we are an Maxsi Engine implementation or not.
//=============================================================================
#if defined(MAXSI_ENGINE_LIBRARY) || defined(MAXSI_ENGINE_CUSTOM_IMPLEMENTION)
#define MAXSI_ENGINE_IMPLEMENTATION
#endif

//=============================================================================
//	Ensure we use the correct import/export syntax for the right platforms.
//=============================================================================
#ifdef _WIN32
	#define MAXSI_DLL_IMPORT_DECL __declspec( dllimport )
	#define MAXSI_DLL_EXPORT_DECL __declspec( dllexport )
#else
	#if __GNUC__ >= 4
		#define MAXSI_DLL_IMPORT_DECL __attribute__ ((visibility("default")))
		#define MAXSI_DLL_EXPORT_DECL __attribute__ ((visibility("default")))
	#else
		#define MAXSI_DLL_IMPORT_DECL
		#define MAXSI_DLL_EXPORT_DECL
	#endif
#endif

//=============================================================================
//	Define import/export Macros
//=============================================================================
#define MAXSI_DLL_IMPORT extern "C" MAXSI_DLL_IMPORT_DECL
#define MAXSI_DLL_EXPORT extern "C" MAXSI_DLL_EXPORT_DECL
#define MAXSI_DLL_IMPORT_CPP extern MAXSI_DLL_IMPORT_DECL
#define MAXSI_DLL_EXPORT_CPP extern MAXSI_DLL_EXPORT_DECL

//=============================================================================
//	Define macros so that projects will link against Maxsi Engine correctly.
//=============================================================================
#ifdef MAXSI_ENGINE_LIBRARY
	//=============================================================================
	//	The following values are used within Maxsi Engine.
	//=============================================================================
	#define LINK MAXSI_DLL_EXPORT
	#define LINKCPP MAXSI_DLL_EXPORT_CPP
	#define CLASSLINK extern "C" class MAXSI_DLL_EXPORT_DECL
	#define CLASSLINKCPP extern "C++" class MAXSI_DLL_EXPORT_DECL
	#define STRUCTLINK extern "C" struct MAXSI_DLL_EXPORT_DECL
	#define STRUCTLINKCPP extern "C++" struct MAXSI_DLL_EXPORT_DECL
#elif defined(MAXSI_ENGINE_CUSTOM_IMPLEMENTION)
	//=============================================================================
	//	The following values are used within projects that use MaxsiEngine
	//	code within itself without linking to Maxsi Engine.
	//=============================================================================
	#define LINK MAXSI_DLL_EXPORT
	#define LINKCPP MAXSI_DLL_EXPORT_CPP
	#define CLASSLINK class
	#define CLASSLINKCPP class
	#define STRUCTLINK struct
	#define STRUCTLINKCPP struct
#else
	//=============================================================================
	//	The following values are used within a normal project that dynamically
	//	links to Maxsi Engine.
	//=============================================================================
	#define LINK MAXSI_DLL_IMPORT
	#define LINKCPP MAXSI_DLL_IMPORT_CPP
	#define CLASSLINK extern "C" class MAXSI_DLL_IMPORT_DECL
	#define CLASSLINKCPP extern "C++" class MAXSI_DLL_IMPORT_DECL
	#define STRUCTLINK extern "C" struct MAXSI_DLL_IMPORT_DECL
	#define STRUCTLINKCPP extern "C++" struct MAXSI_DLL_IMPORT_DECL
#endif

//=============================================================================
//	Interface macros, used to declare classes that are defined elsewhere, or
//	abstract baseclasses, such as the Maxsi Window System. The meaning of the
//	MAXSI_INTERFACE suffix on functions is not defined here and must be
//	#undef'd before and re-#define'd before the class is declared. Afterwards
//	it must be #undef'd and #define'd to emptiness. When #define'd before a
//	class declaration it must be defined to a below macro depending on whether
//	the class is implemented in this library. This allows us to copy-paste the
//	actual class declaration between header files or child classes.
//=============================================================================
// You can use the following macros:
// MAXSI_INTERFACE_VIRTUAL_FUNCTION - This function is not implemented in this binary.
// MAXSI_INTERFACE_IMPLEMENTED_FUNCTION - This function is implemented in this binary.
// MAXSI_INTERFACE_ABSTRACT_BASECLASS - This function is not implemented anywhere because the class is abstract.
// MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_ENGINE - This function is implemented in Maxsi Engine.
// MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE - This function is defined in your application.

#define MAXSI_INTERFACE_VIRTUAL_FUNCTION = 0
#define MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_ABSTRACT_BASECLASS MAXSI_INTERFACE_VIRTUAL_FUNCTION
#ifdef MAXSI_ENGINE_IMPLEMENTATION
#define MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_ENGINE MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE MAXSI_INTERFACE_VIRTUAL_FUNCTION
#else
#define MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_ENGINE MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#endif
#define MAXSI_INTERFACE_RESET_IT_TO_THIS You_Forgot_To_ReDefine_MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_RESET_IT_TO_THIS

//=============================================================================
//	Function-pointer declaration helper macros. TODO: Do we consider this
//	deprecated? It isn't used in any newer code at this moment.
//=============================================================================
#define DECLARE_FUNCTION(return_type, name, parameters) typedef return_type (__cdecl* type_##name  ) parameters ; \
	type_##name name
#define DECLARE_FUNCTION_HEADER(return_type, name, parameters) typedef return_type (__cdecl* type_##name  ) parameters ;
#define DECLARE_FUNCTION_SOURCE(return_type, name, parameters) type_##name name
#define DECLARE_FUNCTION_WINAPI(return_type, name, parameters) typedef return_type (WINAPI* type_##name  ) parameters ; \
	type_##name name
#define DECLARE_EXTERN_FUNCTION(return_type, name, parameters) typedef return_type (__cdecl* type_##name  ) parameters ; \
	extern type_##name name
#define IMPORT_FUNCTION(name) name = reinterpret_cast<type_##name>(GetProcAddress(Executable, #name ));

//=============================================================================
//	A DLL Interface Loading Class - Horribly Deprecated.
//=============================================================================
#if defined(_MSC_VER) && !defined(Maxsi_Disable_Deprecated) // Luckily, we only have to deal with in Visual Studio.
CLASSLINK DLL // Deprecated
{
public:
	char*	DLLPath;
	HMODULE	Executable;

public:
	DLL ( void );
	~DLL ( void );

	void*			ProcAddress	(LPCSTR lpProcName );
	virtual bool	Import	( void );
	virtual bool	Import	( char* LibraryPath );
	bool			Unload	( void );
};

#endif // #idef _MSC_VER

EndMaxsiNamespace

#endif
